#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Author: 宋俊浩

from jenkinsapi.jenkins import Jenkins
from jenkinsapi import custom_exceptions
from jira import JIRA
from jira.exceptions import JIRAError
import re
import sys



def get_matched_data(reg,data):
    return re.compile(reg).findall(data)


class JenkinsMsg(object):
    def __init__(self,msg):
        self.msg = msg

    @property
    def message(self):
        return self.msg

    @property
    def comments(self):
        if self.msg.has_key('msg'):
            return self.msg['msg']
        else:
            return ""
    @property
    def user(self):
        return self.msg['user']


class JenkinsSDK(object):
    def __init__(self):
        pass

    def init(self,jenkins_url, username, password):
        try:
            print("开始连接Jenkins使用地址: %s ,用户名: %s ") % (jenkins_url,username)
            self.j_instance = Jenkins(baseurl=jenkins_url, username=username, password=password)
            return self
        except StandardError as e:
            raise Exception("无法连接Jenkins,请检查用户名密码")

    def param_build(self, job_name, params,cause,return_build_result=False,console_save_path=None):
        """
        Start a Parameterized Build
        """

        # This will start the job in non-blocking manner
        #j.build_job(job_name, params)
        # This will start the job and will return a QueueItem object which
        # can be used to get build results
        try:

            if not self.j_instance.has_job(job_name):
                return False,"Jenkisn中没有这个job，请核对job名"
            else:
                job = self.j_instance.get_job(job_name)
                des = job.get_description()
                print ("开始触发job #%s# , 触发原因为 #%s# ,job描述为 #%s#" % (job_name, cause,des))
                qi = job.invoke(build_params=params,cause=cause)
                # Block this script until build is finished
                if job.is_queued() or job.is_running():
                    qi.block_until_complete()

                '''
                '''
                build_obj = qi.get_build()
                build_result = build_obj.is_good()
                build_cause = build_obj.get_causes()
                build_changeset = build_obj.get_changeset_items()
                #build_revision = build_obj.get_revision()
                build_revision = job.get_last_completed_build().get_revision()
                build_num = qi.get_build_number()
                build_duration = build_obj.get_duration()
                build_result_url = build_obj.get_result_url()
                build_params = build_obj.get_params
                print ("job #%s# 构建完毕，构建编号为 #%d# , 成功? #%s# ,构建花费%s秒,url %s" % (job_name,build_num,build_result,build_duration,build_result_url))

                if console_save_path is not None:
                    build_console = build_obj.get_console()
                    f = open(console_save_path,'w')
                    f.write(build_console)

                if return_build_result:
                    return build_result,\
                            {'build_result':build_result,
                            'build_num':build_num,
                            'build_revision':build_revision,
                            'build_params':build_params,
                            'build_cause':build_cause,
                            'build_changeset':build_changeset,
                            'build_result_url':build_result_url,
                            'build_duration':build_duration}
                else:
                    return build_result,"构建完毕"
        except StandardError as e:
            print e

    def check_job(self,job_name,crontab_time=None, params=None):
        try:
            ##检查jenkins中是否有这个job
            if not self.j_instance.has_job(job_name):
                return False, "Jenkisn中没有这个job，请核对job名"

            ##检查参数名称是否正确，但不检查参数个数，因为有些编译允许使用默认参数
            elif params is not None:
                job = self.j_instance.get_job(job_name)
                job_params_list = job.get_params_list()
                for i in params.keys():
                    if i not in job_params_list:
                        return False,"job #%s# 中没有这个参数 #%s#，请核对参数名" % (job_name,i)
            return True,"检查通过"
        except StandardError as e:
            raise Exception("检查失败")
            return False,e

    def get_job_description(self,job_name):
        job = self.j_instance.get_job(job_name)
        return job.get_description()

    def get_last_sucess_build_changelog(self,job_name):
        job = self.j_instance.get_job(job_name)
        changeset = job.get_last_good_build().get_changeset_items()
        all_changeset = ""
        if changeset:
            try:
                for i in changeset:
                    all_changeset += str(JenkinsMsg(i).comments)
            except custom_exceptions.NotFound as e:
                print "Job %s's %s not found " % (job_name, i)
        else:
            for i in range(job.get_last_failed_buildnumber(), job.get_last_good_buildnumber() + 1):
                try:
                    changeset = job.get_build(buildnumber=i).get_changeset_items()
                    if changeset:
                        for j in changeset:
                            all_changeset += str(JenkinsMsg(j).comments)
                except custom_exceptions.NotFound as e:
                    print "Job %s's %s not found " %(job_name,i)
        return all_changeset

    def get_changeset_bybuildID(self,job_name,build_id):
        job = self.j_instance.get_job(job_name)
        changeset = job.get_build(buildnumber=build_id).get_changeset_items()
        all_changeset = ""
        if changeset:
            try:
                for i in changeset:
                    all_changeset += str(JenkinsMsg(i).comments)
            except custom_exceptions.NotFound as e:
                print "Job %s's %s not found " % (job_name, i)
        else:
            for i in range(job.get_last_failed_buildnumber(), job.get_last_good_buildnumber() + 1):
                try:
                    changeset = job.get_build(buildnumber=i).get_changeset_items()
                    if changeset:
                        for j in changeset:
                            all_changeset += str(JenkinsMsg(j).comments)
                except custom_exceptions.NotFound as e:
                    print "Job %s's %s not found " %(job_name,i)
        return all_changeset







class JIRAHandler(object):
    def __init__(self, username, password):
        self.__username = username
        self.__password = password
        self.__base_url = "http://jira.teamlinker.net"
        self.__options = {
            'server': self.__base_url,
        }

    def conn_jira(self):
        try:
            self.__jira_obj = JIRA(options=self.__options, basic_auth=(self.__username, self.__password))
            return self
        except Exception as e:
            self.__jira_obj = None
            print(e)
            raise Exception("连接不到Jenkins")

    @property
    def jira_obj(self):
        if not self.__jira_obj:
            return self.__jira_obj
        else:
            return None

    @property
    def username(self):
        return self.__username

    @property
    def base_url(self):
        return self.__base_url

    @property
    def isvalidaccount(self):
        try:
            self.conn_jira()
            result = True
        except Exception as e:
            result = False
            print(e)
        finally:
            return result

    def get_issue(self, issue):
        try:
            issue = self.__jira_obj.issue(issue)
        except Exception as e:
            print(e)
            issue = None
        finally:
            return issue

    def docreate(self, project, assignto, summary):
        try:
            issue_dict = {
                'project': {'key': project},
                'assignee': {'name': assignto},
                'summary': summary,
                'description': summary,
                'issuetype': {'name': 'Bug'},
            }
            new_issue = self.__jira_obj.create_issue(fields=issue_dict)
            data = new_issue
        except Exception as e:
            print(e)
            data = None
        finally:
            return data

    def doworklog(self, issue, time, comment):
        try:
            data = self.__jira_obj.add_worklog(issue=issue, timeSpent=time, comment=comment)
        except Exception as e:
            print(e)
            data = None
        finally:
            return data

    def docomment(self, issue, comment):
        try:
            data = self.__jira_obj.add_comment(issue=issue, body=comment)
        except Exception as e:
            print(e)
            data = None
        finally:
            return data

    def transact(self, issue, action, comment=None):
        try:
            data = self.__jira_obj.transition_issue(issue=issue, transition=action.lower(), comment=comment)
            print data
        except Exception as e:
            print(e)
            data = None
        finally:
            return data



def get_jira_issue_from_changeset(jenkins_job_name):
    j = JenkinsSDK().init("http://192.168.2.12:8080/jenkins", "sdg", "wkopny976")
    passed, data = j.check_job(job_name=jenkins_job_name)
    if passed:
        print "jenkins have this job,get changeset...."
        data = get_matched_data('\w{1,}-\d{1,}', j.get_last_sucess_build_changelog(jenkins_job_name))
        return list(set(data))
    else:
        print "jenkins dont have this job"
        return None

if __name__ == "__main__":
    if len(sys.argv) == 1:
        print "Must specify jenkins job name as first argument"
        exit(1)
    job_name = sys.argv[1]
    J_SITE_NAME = "子午线JIRA http://jira.teamlinker.net"
    J_BASE_URL = "http://jira.teamlinker.net"
    J_USERNAME = "mBot"
    J_PASSWORD = "P@ssword123"
    options = {
        'server': J_BASE_URL,
    }
    jira = JIRA(options=options, basic_auth=(J_USERNAME, J_PASSWORD))
    jira_issue_list = get_jira_issue_from_changeset(job_name)
    if jira_issue_list:
        for i in jira_issue_list:
            try:
                jira.transition_issue(issue=jira.issue(i), transition="Resolve Issue",
                                      comment=u"Issue Resolved,并已发布到内部测试环境")
                print "%s resolved" % i
            except JIRAError as e:
                print "Don't have this issue %s , or this issues's status have been already Resolved " % i
                continue
    print "issues %s reloved" % jira_issue_list
